﻿using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace MVBuddy.Common.Helpers
{
    public class HtmlRequest
    {
        private HttpWebRequest webRequest;

        public Uri Uri { get; set; }
        public string Method { get; set; }
        public string ContentType { get; set; }
        public Dictionary<string, string> Parameters { get; private set; }

        public HtmlRequest(Uri uri)
            : this(uri, "GET", string.Empty, new Dictionary<string, string>())
        {
        }

        public HtmlRequest(Uri uri, string method, string contentType, Dictionary<string, string> parameters)
        {
            this.Uri = uri;
            this.Method = method;
            this.ContentType = contentType;
            this.Parameters = parameters;
        }

        public async Task<HtmlDocument> DoRequest()
        {
            this.webRequest = (HttpWebRequest)HttpWebRequest.CreateHttp(this.Uri);
            this.webRequest.Method = this.Method;
            this.webRequest.ContentType = this.ContentType;
            this.webRequest.CookieContainer = new CookieContainer();

            if (this.Method == "POST")
            {
                await this.SendPostData();
            }

            return await this.GetWebContent();
        }

        private async Task SendPostData()
        {
            await Task<Stream>.Factory.FromAsync(this.webRequest.BeginGetRequestStream, this.webRequest.EndGetRequestStream, this.webRequest)
                .ContinueWith(streamResult =>
                {
                    using (Stream postStream = streamResult.Result)
                    {
                        string postData = string.Empty;
                        int count = 0;

                        foreach (KeyValuePair<string, string> kvp in this.Parameters)
                        {
                            postData += kvp.Key + "=" + kvp.Value;

                            if (++count < this.Parameters.Count)
                            {
                                postData += "&";
                            }
                        }

                        byte[] byteArray = Encoding.UTF8.GetBytes(postData);

                        postStream.Write(byteArray, 0, byteArray.Length);
                    }
                });
        }

        private async Task<HtmlDocument> GetWebContent()
        {
            return await Task<WebResponse>.Factory.FromAsync(this.webRequest.BeginGetResponse, this.webRequest.EndGetResponse, this.webRequest)
                .ContinueWith<HtmlDocument>(webResponseResult =>
                    {
                        HtmlDocument document = new HtmlDocument();

                        try
                        {
                            using (HttpWebResponse response = (HttpWebResponse)webResponseResult.Result)
                            {
                                using (StreamReader streamRead = new StreamReader(response.GetResponseStream()))
                                {
                                    string responseString = streamRead.ReadToEnd();

                                    document.LoadHtml(responseString);
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            document = null;
                        }

                        return document;
                    });
        }
    }
}